package cinema;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.InputMismatchException;
import java.util.Map;
import java.util.Scanner;

import cinema.Movie.Detail;

/**
 * @author Matt Couzens & Amanda Kosinski
 * @version 29 April 2012
 */
public class Menu {

	private static BookingSystem sys;
	private static Scanner sc;
	private static ArrayList<Showing> showList;
	private static boolean loop;

	// Booking system main menu. It does not ask for a log in at this stage as we wanted customers 
	// to be able to view movies on offer before creating an account or logging in to book a ticket.
	// This is based on existing systems on the web.
	static void mainMenu(BookingSystem bs){
		loop = true;
		sys = bs;
		do{
			System.out.println("\n<<< Main Menu >>>");
			System.out.println("\nPlease enter a number to make a selection:");
			System.out.println("\t1. View movies by title"); 
			System.out.println("\t2. View movies by date");
			System.out.println("\t3. View showings archive");
			System.out.println("\t4. My account");
			System.out.println("\t0. Exit");
			System.out.println("\n\t9. Manager login"); 
			sc = new Scanner(System.in);
			try{
				int selection = sc.nextInt();
				switch (selection) {
				case 0: 
					loop = false;
					break;
				case 1:
					setShowlistFuture();
					loop = displayMoviesByTitle();
					break;
				case 2:
					setShowlistFuture();
					loop = displayShowingsByDate(0);
					break;
				case 3: 
					loop = displayPastShowings();
					break;
				case 4:
					loop = myAccount();
					break;
				case 9:
					loop = managerMenu();
					break;
				default:
					System.out.println("Invalid selection");
					break;
				}
			} catch (InputMismatchException exception){
				System.out.println("Input was not a number");
			}
		}while(loop);
	}

	static void setShowlistFuture(){
		ArrayList<Showing> nowShowing = sys.getShowings();
		showList = (ArrayList<Showing>) nowShowing.clone();
		filterShowingsByDate(Calendar.getInstance(), 1);
	}

	static void setShowlistPast(){
		ArrayList<Showing> nowShowing = sys.getShowings();
		showList = (ArrayList<Showing>) nowShowing.clone();
		filterShowingsByDate(Calendar.getInstance(), -1);
	}

	/**
	 * Given a list of showings, display a numbered list of dates for those showings, and prompt for selection
	 * 
	 * @param showList the ArrayList of Showing objects to be displayed
	 * @param dateOption (passed to dateToString method) '0' to display the date only (E dd MMM yyyy); 
	 * 													 '1' to display the date and time (E dd MMM yyyy HH:mm)
	 */
	// Option 2 from main menu
	static boolean displayShowingsByDate(int dateOption){
		if(showList.size() == 0){
			System.out.println("No movies.");
			return true;
		}
		int index = 1;
		ArrayList<Calendar> dateList = new ArrayList<Calendar>(); // contains dates only (no times), used by for loop to prevent duplicate dates in dateMap
		HashMap<Integer, Calendar> dateMap = new HashMap<Integer, Calendar>(); // contains dates (including times), used for user selection
		System.out.println("Please make a selection:");
		for (Showing show : showList){
			Calendar date = show.getShowtime();
			if (!dateList.contains(removeTime(date))){							// Show each date only once
				String str = Utility.dateToString(date, dateOption);	// Convert to a date only (i.e. no time) String 
				System.out.println("\t" + index + ": " + str);
				dateList.add(removeTime(date));
				dateMap.put(index, date);
				index++;
			}
		}
		sc = new Scanner(System.in);
		int selection = sc.nextInt();
		filterShowingsByDate(dateMap.get(selection), 0);
		return displayMoviesByTitle();
	}

	/**
	 * 
	 * @return
	 */
	static boolean displayPastShowings(){
		setShowlistPast();
		if(showList.size() == 0){
			System.out.println("No showings.");
			return true;
		}
		System.out.println("Archived showings:");
		for (Showing show : showList){
			System.out.println("\t" + show.toString());
		}
		return true;
	}

	/**
	 * Given a list of showings, displays the movie title for each showing and prompts for input to select a movie.
	 * 
	 * @param showList an ArrayList of Showing objects 
	 * @return the selected Movie object
	 */
	//Option 1 from main menu
	static boolean displayMoviesByTitle(){
		if(showList.size() == 0){
			System.out.println("No movies.");
			return true;
		}
		System.out.println("Please make a selection:");
		int index = 1;
		HashMap<Integer, Movie> movieMap = new HashMap<Integer, Movie>();
		for (Showing show : showList){
			Movie mv = show.getMovie();
			if (!movieMap.containsValue(mv)){				// Display each movie only once
				System.out.println("\t" + index + ": " + mv.getMovieDetails(Detail.Title));
				movieMap.put(index, mv);
				index++;
			}
		}
		sc = new Scanner(System.in);
		int selection = sc.nextInt();
		return movieOptions(movieMap.get(selection));
	}

	static boolean movieOptions(Movie mv) {
		System.out.println("Movie details:\n");
		mv.getMovieDetails();
		System.out.println("\nSelect a showing:\n");
		int index = 1;
		HashMap<Integer, Showing> showMap = new HashMap<Integer, Showing>();
		for(Showing sh : showList){
			if(sh.getMovie() == mv){
				System.out.print("" + index + ": " + sh.toString());
				System.out.println(" (" + availableSeats(sh) +" seats available)");
				showMap.put(index, sh);
				index++;
			}
		}
		System.out.println("\n-1. Go back");
		sc = new Scanner(System.in);
		int selection = sc.nextInt();
		if(selection == -1) return true;
		return makeBooking(showMap.get(selection));
	}

	static boolean makeBooking(Showing show){
		int seats;
		int available = availableSeats(show);
		if (available < 1){
			System.out.println("No available seats, please choose another showing.");
			return true;
		}
		loop = true;
		do{
			do{
				System.out.println("How many seats would you like for " + show.toString() + "?");
				sc = new Scanner(System.in);
				seats = sc.nextInt();
				if(seats > available){
					System.out.println("Only " + available + " seats are available");
				}
			} while(seats > available);
			if(sys.getLoggedInUser() == null){
				System.out.println("Select -1 to go back, 0 to exit, 1 to login, or 2 to create an account:");
				int selection = sc.nextInt();
				switch (selection) {
				case -1:
					return true;
				case 0:
					return false;
				case 1: 
					if (!sys.login()){
						System.out.print("Invalid username or password, returning to main menu.");
						return true;
					}
					else loop = false;
					break;
				case 2:
					loop = !sys.newCustomer();
					System.out.println("\nPlease login:");
					if (!sys.login()){
						return true;
					}
					else loop = false;
					break;
				default:
					System.out.println("Invalid selection");
					break;
				}
			}
			else loop = false;
		}while(loop);
		return makePayment(show, seats);
	}

	static boolean makePayment(Showing show, int seats){
		do{
			System.out.println("Select a payment method:");
			System.out.println("\t1. Visa");
			System.out.println("\t2. Mastercard");
			sc = new Scanner(System.in);
			int selection = sc.nextInt();
			switch (selection) {
			case -1:
				return true;
			case 0:
				return false;
			case 1:
				System.out.println("Selected: Visa");
				loop = false;
				break;
			case 2:
				System.out.println("Selected: Mastercard");
				loop = false;
				break;
			default:
				System.out.println("Invalid selection");
				loop = false;
				break;
			}
			Booking bk = new Booking(show, sys.getLoggedInUser(), seats);
			System.out.println("Booking complete.");
			System.out.println("Your booking reference is: " + (sys.getBookingRef()));
			sys.addBooking(bk);
			Utility.save(sys);
			return true;
		}while(loop);
	}

	//Option 4 from Main Menu
	static boolean myAccount() {
		if(sys.login()){
			if(sys.getLoggedInUser() == sys.getMgr()){
				System.out.println("Customers only");
				return true;
			}
			do{
				System.out.println("\n<<< My account >>>\n"); 
				System.out.println("Please make a selection:");
				System.out.println("\t1. View or cancel bookings");
				System.out.println("\t2. Change password");
				System.out.println("\t3. View and/or change address");
				System.out.println("\t4. Change payment method");
				System.out.println("\n\t-1. Back");
				System.out.println("\t0.  Exit");
				Scanner sc = new Scanner(System.in);
				int selection = sc.nextInt();
				switch (selection) {
				case -1:
					return true;
				case 0:
					return false;				
				case 1:
					loop = myBookings();
					break;
				case 2:
					loop = changePassword();
					break;
				case 3:
					loop = changeAddress();
					break;
				case 4:
					loop = changePaymentMethod();
					break;
				default:
					System.out.println("Invalid selection");
					break;
				}
			}while(loop);
		}
		else sys.goodbye();
		return false;
	}		

	static boolean myBookings() {
		int selection;
		System.out.println("Your bookings.\nPlease enter the reference number of the booking you wish to cancel:");
		System.out.println("(or -1 to go back, 0 to exit)\n");
		ArrayList<Integer> bkrefList = new ArrayList<Integer>();
		for(Integer bkref : sys.getBookings().keySet()){
			Booking bk = sys.getBookings().get(bkref);
			if(bk.getPerson() == sys.getLoggedInUser()){
				System.out.println("\tBooking ref: " + bkref + " -> " + bk.toString());
				bkrefList.add(bkref);
			}
		}
		Scanner sc = new Scanner(System.in);
		selection = sc.nextInt();
		if(bkrefList.contains(selection)){
			cancelBooking(selection);
		}
		else System.out.println("Invalid booking reference.");
		return true;
	}

	static boolean cancelBooking(int bkref){
		double refund = calculateRefund(bkref);
		if (refund == -1){
			System.out.println("Past bookings cannot be cancelled.");
			return true;
		}
		System.out.println("Subject to " + (int)(refund * 100) + "% refund.");
		System.out.println("Are you sure you want to cancel this booking? (y/n)");
		Scanner sc = new Scanner(System.in);
		String selection = sc.next();
		if(selection.equals("y")){
			sys.deleteBooking(bkref);
			System.out.println("Booking ref " + bkref + " has been cancelled.");
			System.out.println("" + (int)(refund * 100) + "% of the booking price has been refunded to your card.");
		}
		Utility.save(sys);
		return true;
	}

	/**
	 * Booking can be cancelled up to 24 hours before the showing of the film.
	 * If cancelled 78 hours before the show time then customers get a full refund; 
	 * 
	 * 78 hours 100%;
	 * 48 hours 50%;
	 * 24 hours 25%. 
	 * Later cancellations are possible but no refund is given but the seat(s) become(s) available again.
	 * Past booking cannot be cancelled.
	 */
	static double calculateRefund(int bkref){
		Booking bk = sys.getBooking(bkref);
		double fullRefund = 1;
		double halfRefund = 0.5;
		double quarterRefund = 0.25;
		double noRefund = 0;
		double pastBooking = -1;
		int fullRefundTime = 78 * 60 * 60 * 1000;
		int halfRefundTime = 48 * 60 * 60 * 1000;
		int quarterRefundTime = 24 * 60 * 60 * 1000;
		long bookingDate = bk.getShowing().getShowtime().getTimeInMillis();
		long now = Calendar.getInstance().getTimeInMillis();
		long timeDiff = bookingDate - now;
		// Next line added for debugging
		// System.out.println("timeDiff = " + (timeDiff/60/60/1000) + "hours.");
		if(timeDiff >= fullRefundTime){
			return fullRefund;
		}
		else if(timeDiff >= halfRefundTime){
			return halfRefund;
		}
		else if(timeDiff >= quarterRefundTime){
			return quarterRefund;
		}
		else if(timeDiff <= 0){
			return pastBooking;
		}
		else return noRefund;
	}

	static boolean changePassword() {
		Scanner sc = new Scanner(System.in);
		System.out.println("Please enter a new password: ");
		String password = sc.nextLine();
		sys.getLoggedInUser().setPassword(password);
		System.out.println(sys.getLoggedInUser().getPassword());
		Utility.save(sys);
		return true;
	}

	private static boolean changeAddress() {
		Customer c = sys.getCustomers().get(sys.getLoggedInUser().getUsername());
		sc = new Scanner(System.in);
		System.out.println("Your current address is:");
		System.out.println(c.getAddress());
		System.out.println("Enter '1' to change address, or '-1' to return to the main menu:");
		int selection = sc.nextInt();
		if (selection == 1) {
			System.out.println("Please enter your new address on one line seperated by commas:");
			sc = new Scanner(System.in);
			String newAddress = sc.nextLine();
			c.setAddress(newAddress);
		}
		Utility.save(sys);
		return true;
	}

	private static boolean changePaymentMethod() {
		Customer c = sys.getCustomers().get(sys.getLoggedInUser().getUsername());
		sc = new Scanner(System.in);
		System.out.println("Your current payment methods is:");
		System.out.println(c.getPaymentType());
		System.out.println("Enter '1' to change address, or '-1' to return to the main menu:");
		int selection = sc.nextInt();
		if (selection == 1) {
			System.out.println("Please enter your new address on one line seperated by commas:");
			sc = new Scanner(System.in);
			String newAddress = sc.nextLine();
			c.setAddress(newAddress);
		}
		Utility.save(sys);
		return true;
	}

	/**
	 * For a given list of showings, returns a filtered list of showings for a given movie.
	 * 
	 * @param showList the list of showings to be filtered
	 * @param movie the movie on which to filter
	 * @return the filtered list of showings
	 */
	static void filterShowingsByMovie(Movie movie){
		ArrayList<Showing> sh = new ArrayList<Showing>();
		for (Showing s : showList){
			if(movie == s.getMovie()){
				sh.add(s);
			}
		}
		showList = sh;
	}

	/**
	 * For a given list of showings, returns a filtered list of showings either before or after a given date and time, or on a given date only.
	 * 
	 * @param showList the ArrayList of Showing objects to be filtered
	 * @param date the Calendar object on which to filter
	 * @param option '-1' for before the given date; '0' for on the date (time ignored); '1' for after the date
	 * @return the filtered ArrayList of Showing objects
	 */
	static void filterShowingsByDate(Calendar date, int option){
		ArrayList<Showing> sh = new ArrayList<Showing>();
		if(option == -1) {
			for (Showing s : showList){
				if((s.getShowtime().before(date))){
					sh.add(s);
				}
			}
		}
		if(option == 0) {
			for (Showing s : showList){
				if(removeTime(date).equals(removeTime(s.getShowtime()))){
					sh.add(s);
				}
			}
		}
		if(option == 1) {
			for (Showing s : showList){
				if(date.before(s.getShowtime())){
					sh.add(s);
				}
			}
		}
		showList = sh;
	}

	static void sortShowingsByDate(){
		Collections.sort(showList, new Comparator<Showing>() {
			public int compare(Showing s1, Showing s2) {
				return s1.getShowtime().compareTo(s2.getShowtime());
			}
		});
	}

	/**
	 * @param cal
	 * @return
	 */
	static Calendar removeTime(Calendar cal){
		Calendar cal1 = Calendar.getInstance();
		cal1.clear();
		cal1.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH));
		return cal1;
	}

	static int availableSeats(Showing sh){
		return sh.getScreen().getCapacity() - sh.getBookedSeats();
	}

	/* -------------------------------------------------------------------------------------------
	 * ---------- Manager Menu -------------------------------------------------------------------
	 * -------------------------------------------------------------------------------------------
	 */

	private static boolean managerMenu() {
		loop = true;
		sys.login();
		if(!(sys.getLoggedInUser() == sys.getMgr())){
			System.out.println("Access denied!");
			return true;
		}
		do{
			System.out.println("\n<<< Manager Menu >>>");
			System.out.println("\nWhich of the following would you like to add, view, edit, or delete?:");
			System.out.println("\t1. Movies");
			System.out.println("\t2. Showings");
			System.out.println("\t3. Bookings");
			System.out.println("\t4. Screens");
			System.out.println("\n\t0. Exit");
			sc = new Scanner(System.in);
			int selection = sc.nextInt();
			switch (selection) {
			case 0: 
				return false;
			case 1:
				loop = managerMenuMovies();
				break;
			case 2: 
				loop = managerMenuShowings();
				break;
			case 3:
				loop = managerMenuBookings();
				break;
			case 4:
				loop = managerMenuScreens();
				break;
			default:
				System.out.println("Invalid selection");
				break;
			}
		}while(loop);
		return true;
	}

	private static boolean managerMenuMovies() {
		loop = true;
		do{
			System.out.println("\n<<< Manager movies menu >>>\n");
			System.out.println("Please make a selection:");
			System.out.println("\t1. Add movie");
			System.out.println("\t2. View, edit or delete movies");
			System.out.println("\n\t-1. Back to main menu");
			sc = new Scanner(System.in);
			int selection = sc.nextInt();
			switch (selection) {
			case -1: 
				return false;
			case 1:
				loop = addMovie();
				break;
			case 2:
				loop = manageMovie(viewAllMovies());
				break;
			default:
				System.out.println("Invalid selection");
				break;
			}
		}while(loop);
		return false;
	}

	static boolean addMovie(){
		sc = new Scanner(System.in);
		System.out.println("Enter movie title:");
		String title = sc.nextLine();
		System.out.println("Enter genre:");
		String genre = sc.nextLine();
		System.out.println("Enter director:");
		String director = sc.nextLine();
		System.out.println("Enter movie length:");
		String length = sc.nextLine();
		System.out.println("Enter cast list:");
		String cast = sc.nextLine();
		System.out.println("Enter release date:");
		String releaseDate = sc.nextLine();
		System.out.println("Enter certificate:");
		String certificate = sc.nextLine();
		System.out.println("Enter language:");
		String language = sc.nextLine();
		System.out.println("Enter synopsis:");
		String synopsis = sc.nextLine();
		System.out.println("Enter trailer URL:");
		String trailer = sc.nextLine();
		sys.addMovie(
				title, 
				genre, 
				director, 
				length, 
				cast, 
				releaseDate, 
				certificate, 
				language, 
				synopsis, 
				trailer);
		Utility.save(sys);
		return true;
	}

	static Movie viewAllMovies(){
		int index = 1;
		HashMap<Integer, Movie> movieMap = new HashMap<Integer, Movie>();
		for (Movie mv : sys.getMovies()){
			System.out.println("\t" + index + ": " + mv.getMovieDetails(Detail.Title));
			movieMap.put(index, mv);
			index++;
		}
		sc = new Scanner(System.in);
		int selection = sc.nextInt();
		return movieMap.get(selection);
	}

	static boolean manageMovie(Movie mv){
		loop = true;
		do{
			System.out.println("Please make a selection:");
			System.out.println("\t1. View movie details");
			System.out.println("\t2. Edit movie");
			System.out.println("\t3. Delete movie");
			System.out.println("\n\t0. Exit");
			sc = new Scanner(System.in);
			int selection = sc.nextInt();
			switch (selection) {
			case 0: 
				return false;
			case 1:
				mv.getMovieDetails();
				loop = false;
				break;
			case 2:
				mv.editMovie();
				loop = false;
				break;
			case 3:
				deleteMovie(mv);
				loop = false;
				break;
			default:
				System.out.println("Invalid selection");
				break;
			}
		}while(loop);
		return true;
	}

	static boolean deleteMovie(Movie mv){
		sys.deleteMovie(mv);
		// Remove all associated showings to prevent null pointer exceptions
		for(Showing sh : sys.getShowings()){
			if(mv == sh.getMovie()){
				deleteShowing(sh);
			}
		}
		System.out.println("Movie successfully deleted.");
		Utility.save(sys);
		return true;
	}

	private static boolean managerMenuShowings() {
		loop = true;
		do{
			System.out.println("\n<<< Manager showings menu >>>\n");
			System.out.println("Please make a selection:");
			System.out.println("\t1. Add showing");
			System.out.println("\t2. View, edit or delete showings");
			System.out.println("\n\t0. Exit");
			sc = new Scanner(System.in);
			int selection = sc.nextInt();
			switch (selection) {
			case 0: 
				return false;
			case 1:
				loop = addShowing();
				break;
			case 2:
				manageShowing(viewAllShowings());
				break;
			default:
				System.out.println("Invalid selection");
				break;
			}
		}while(loop);
		return false;
	}

	private static boolean addShowing() {
		Movie mv = viewAllMovies();
		System.out.println("Please enter a screen number from the list below:");
		for(Integer scrNum : sys.getScreens().keySet()){
			System.out.println("Screen " + scrNum);
		}
		int screen = sc.nextInt();
		System.out.println("Please enter the year:");
		int year = sc.nextInt() + 1900;
		System.out.println("Please enter the month:");
		int month = sc.nextInt();
		System.out.println("Please enter the day of month:");
		int date = sc.nextInt();
		System.out.println("Please enter the hour of day:");
		int hr = sc.nextInt();
		System.out.println("Please enter the minutes of hour:");
		int min = sc.nextInt();
		sys.addShowing(mv, screen, year, month, date, hr, min);
		Utility.save(sys);
		return true;
	}

	private static Showing viewAllShowings() {
		int index = 1;
		HashMap<Integer, Showing> showingMap = new HashMap<Integer, Showing>();
		for (Showing sh : sys.getShowings()){
			System.out.println("\t" + index + ": " + sh.toString());
			showingMap.put(index, sh);
			index++;
		}
		sc = new Scanner(System.in);
		int selection = sc.nextInt();
		return showingMap.get(selection);
	}

	static boolean manageShowing(Showing sh){
		loop = true;
		do{
			System.out.println("Please make a selection:");
			System.out.println("\t1. View showing details");
			System.out.println("\t2. Edit showing");
			System.out.println("\t3. Delete showing");
			System.out.println("\n\t0. Exit");
			sc = new Scanner(System.in);
			int selection = sc.nextInt();
			switch (selection) {
			case 0: 
				return false;
			case 1:
				sh.toString();
				loop = false;
				break;
			case 2:
				editShowing(sh);
				loop = false;
				break;
			case 3:
				System.out.println("Warning: deleting this showing will delete all associated bookings.");		
				System.out.println("Are you sure you want to continue? (y/n)");
				sc = new Scanner(System.in);
				String confirm = sc.next();
				if(confirm.equals("y")){
					deleteShowing(sh);
					System.out.println("Showing successfully deleted.");
				}
				loop = false;
				break;
			default:
				System.out.println("Invalid selection");
				break;
			}
		}while(loop);
		return true;
	}

	private static boolean editShowing(Showing sh) {
		loop = true;
		do{
			System.out.println("Which detail would you like to change?");
			System.out.println("\t1. Change movie");
			System.out.println("\t2. Change screen");
			System.out.println("\t3. Change showtime");
			System.out.println("\n\t0. Exit");
			sc = new Scanner(System.in);
			int selection = sc.nextInt();
			switch (selection) {
			case 0: 
				return false;
			case 1:
				sh.setMovie(viewAllMovies());
				Utility.save(sys);
				loop = false;
				break;
			case 2:
				sh.setScreen(viewAllScreens());
				Utility.save(sys);
				loop = false;
				break;
			case 3:
				System.out.println("Please enter the year (e.g. 2012):");
				int year = sc.nextInt();
				System.out.println("Please enter the month (1-12):");
				int month = sc.nextInt() - 1;
				System.out.println("Please enter the day of month (1-31):");
				int date = sc.nextInt();
				System.out.println("Please enter the hour of day (0-23):");
				int hr = sc.nextInt();
				System.out.println("Please enter the minutes of hour (0-59):");
				int min = sc.nextInt();				
				Calendar newShowtime = new GregorianCalendar(year, month, date, hr, min);
				sh.setShowtime(newShowtime);
				System.out.println("New showing details are:");
				System.out.println(sh.toString());
				Utility.save(sys);
				loop = false;
				break;
			default:
				System.out.println("Invalid selection");
				break;
			}
		}while(loop);
		return true; //returns you to main menu
	}

	private static boolean deleteShowing(Showing sh) {
		// Deletes associated bookings
		ArrayList<Integer> deletedBkrefs = new ArrayList<Integer>();
		Map<Integer, Booking> bookings = sys.getBookings();
		for (Integer bknum : bookings.keySet()){
			Booking booking = bookings.get(bknum);
			if(booking.getShowing().equals(sh)){
				bookings.remove(booking);
				deletedBkrefs.add(bknum);
			}
		}
		sys.deleteShowing(sh);
		System.out.println("Showing deleted, along with the following booking refs:");
		for(int bkref : deletedBkrefs){
			System.out.println("\t" + bkref);
		}
		System.out.println("The customers have been notified and refunded");
		Utility.save(sys);
		return true;
	}

	private static boolean managerMenuBookings() {
		loop = true;
		do{
			System.out.println("\n<<< Manager bookings menu >>>\n");
			System.out.println("Please make a selection:");
			System.out.println("\t1. Add booking");
			System.out.println("\t2. View, edit or delete booking");
			System.out.println("\n\t0. Exit");
			sc = new Scanner(System.in);
			int selection = sc.nextInt();
			switch (selection) {
			case 0: 
				return false;
			case 1:
				loop = addBooking();
				break;
			case 2:
				loop = manageBooking(viewAllBookings());
				break;
			default:
				System.out.println("Invalid selection");
				break;
			}
		}while(loop);
		return false;
	}

	private static boolean addBooking() {
		System.out.println("Please select a showing:");
		Showing show = viewAllShowings();
		System.out.println("Please select a customer:");
		int index = 1;
		Map<Integer, String> usernameMap = new HashMap<Integer, String>();
		for (String username : sys.getCustomers().keySet()){
			System.out.println("\t" + index + ": " + username);
			usernameMap.put(index, username);
			index++;
		}
		int selection = sc.nextInt();
		Person person = sys.getCustomers().get(usernameMap.get(selection));
		System.out.println("Please enter the number of seats:");
		int seats = sc.nextInt();
		Booking bk = new Booking(show, person, seats);
		sys.addBooking(bk);
		System.out.println("New booking successfully added:");
		System.out.println(bk.toString());
		Utility.save(sys);
		return true;
	}

	private static int viewAllBookings() {
		int selection;
		boolean valid;
		do{
			System.out.println("Listing all bookings:");
			for (Integer bkref : sys.getBookings().keySet()){
				System.out.println("\tBooking ref " + bkref + ": " + sys.getBookings().get(bkref).toString());
			}
			System.out.println("Type in a booking ref to select:");
			sc = new Scanner(System.in);
			selection = sc.nextInt();
			valid = sys.getBookings().containsKey(selection);
			if(!valid) System.out.println("Invalid selection.\n");
		}while(!valid);
		return selection;
	}

	private static boolean manageBooking(int bkref) {
		loop = true;
		do{
			System.out.println("Please make a selection:");
			System.out.println("\t1. View booking details");
			System.out.println("\t2. Edit booking");
			System.out.println("\t3. Delete booking");
			System.out.println("\n\t0. Exit");
			sc = new Scanner(System.in);
			int selection = sc.nextInt();
			switch (selection) {
			case 0: 
				return true;
			case 1:
				System.out.println(sys.getBookings().get(bkref).toString());
				loop = false;
				break;
			case 2:
				loop = !editBooking(bkref);
				break;
			case 3:
				loop = !deleteBooking(bkref);
				System.out.println("Booking successfully deleted.");
				break;
			default:
				System.out.println("Invalid selection");
				break;
			}
		}while(loop);
		return true;

	}

	private static boolean editBooking(int bkref) {
		loop = true;
		do{
			System.out.println("Which detail would you like to change?");
			System.out.println("\t1. Change showing");
			System.out.println("\t2. Change number of seats");
			System.out.println("\t3. Change customer");
			System.out.println("\n\t0. Exit");
			sc = new Scanner(System.in);
			int selection = sc.nextInt();
			switch (selection) {
			case 0: 
				return false;
			case 1:
				System.out.println("Select a showing:");
				sys.getBookings().get(bkref).setShowing(viewAllShowings());
				Utility.save(sys);
				return true;
			case 2:
				System.out.println("Enter new number of seats:");
				sc = new Scanner(System.in);
				int seats = sc.nextInt();
				sys.getBookings().get(bkref).setSeats(seats);
				Utility.save(sys);
				return true;
			case 3:
				int choice;
				int index = 1;
				boolean valid;
				HashMap<Integer, String> customerMap = new HashMap<Integer, String>();
				do{
					System.out.println("Select a customer:");
					for(String username : sys.getCustomers().keySet()){
						System.out.println("\t" + index + ": " + username);
						customerMap.put(index, username);
						index++;
					}
					sc = new Scanner(System.in);
					choice = sc.nextInt();
					valid = customerMap.containsKey(choice);
					if(!valid) System.out.println("Invalid selection.\n");
				}while(!valid);
				String uname = customerMap.get(choice);
				sys.getBookings().get(bkref).setPerson(sys.getCustomers().get(uname));
				Utility.save(sys);
				return true;
			default:
				System.out.println("Invalid selection");
				break;
			}
		}while(loop);
		return true; //returns you to main menu
	}

	private static boolean deleteBooking(int bkref) {
		sys.getBookings().remove(bkref);
		Utility.save(sys);
		return true;
	}

	private static boolean managerMenuScreens() {
		loop = true;
		do{
			System.out.println("\n<<< Manager screens menu >>>\n");
			System.out.println("Please make a selection:");
			System.out.println("\t1. Add screen");
			System.out.println("\t2. View, edit or delete screen");
			System.out.println("\n\t0. Exit");
			sc = new Scanner(System.in);
			int selection = sc.nextInt();
			switch (selection) {
			case 0: 
				return false;
			case 1:
				loop = addScreen();
				break;
			case 2:
				manageScreen(viewAllScreens());
				break;
			default:
				System.out.println("Invalid selection");
				break;
			}
		}while(loop);
		return false;
	}

	private static boolean addScreen() {
		System.out.println("Please enter the screen number:");
		int screenNumber = sc.nextInt();
		if(sys.getScreens().containsKey(screenNumber)){
			System.out.println("This screen number already exists.");
			return true;
		}
		System.out.println("Please enter the capacity:");
		int capacity = sc.nextInt();
		System.out.println("Please enter the layout information:");
		sc = new Scanner(System.in);
		String layout = sc.nextLine();
		sys.addScreen(screenNumber, capacity, layout);
		System.out.println("New screen successfully added.");
		Utility.save(sys);
		return true;
	}

	private static Screen viewAllScreens() {
		int selection;
		boolean valid;
		do{
			System.out.println("Select a screen:");
			for (Integer scrNum : sys.getScreens().keySet()){
				System.out.println("\t" + scrNum);
			}
			sc = new Scanner(System.in);
			selection = sc.nextInt();
			valid = sys.getScreens().containsKey(selection);
			if(!valid) System.out.println("Invalid selection.\n");
		}while(!valid);
		return sys.getScreens().get(selection);
	}

	static boolean manageScreen(Screen scr){
		loop = true;
		do{
			System.out.println("Please make a selection:");
			System.out.println("\t1. View screen details");
			System.out.println("\t2. Edit screen");
			System.out.println("\t3. Delete screen");
			System.out.println("\n\t0. Exit");
			sc = new Scanner(System.in);
			int selection = sc.nextInt();
			switch (selection) {
			case 0: 
				return false;
			case 1:
				System.out.println(scr.toString());
				loop = false;
				break;
			case 2:
				loop = editScreen(scr);
				break;
			case 3:
				deleteScreen(scr);
				System.out.println("Screen successfully deleted.");
				loop = false;
				break;
			default:
				System.out.println("Invalid selection");
				break;
			}
		}while(loop);
		return true;
	}

	private static boolean editScreen(Screen scr) {
		loop = true;
		do{
			System.out.println("Which detail would you like to change?");
			System.out.println("\t1. Change screen number");
			System.out.println("\t2. Change capacity");
			System.out.println("\t3. Change layout");
			System.out.println("\n\t0. Exit");
			int scrNum = scr.getScreenNumber();
			sc = new Scanner(System.in);
			int selection = sc.nextInt();
			switch (selection) {
			case 0: 
				return false;
			case 1:
				System.out.println("Enter new screen number:");
				int newScrNum = sc.nextInt();
				if(sys.getScreens().containsKey(newScrNum)){
					System.out.println("This screen number already exists.");
					break;
				}
				scr.setScreenNumber(newScrNum);
				// Next two lines update the HashMap in BookingSystem
				sys.getScreens().remove(scrNum);
				sys.getScreens().put(newScrNum, scr);
				Utility.save(sys);
				loop = false;
				break;
			case 2:
				System.out.println("Enter new capacity:");
				int newCapacity = sc.nextInt();
				scr.setCapacity(newCapacity);
				Utility.save(sys);
				loop = false;
				break;
			case 3:
				System.out.println("Please enter the new layout:");
				String str = sc.nextLine();
				scr.setLayout(str);
				Utility.save(sys);
				loop = false;
				break;
			default:
				System.out.println("Invalid selection");
				break;
			}
		}while(loop);
		return true; //returns you to main menu
	}

	private static void deleteScreen(Screen scr) {
		sys.getScreens().remove(scr.getScreenNumber());
		Utility.save(sys);
	}
}

